// SharpF2.cpp : Implementation of CSharpF2

#include "stdafx.h"
#include "SharpF2.h"
#include <atlconv.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <windows.h>

// CSharpF2

HRESULT CSharpF2::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDO, HKEY hProgID )
{
	TCHAR     szFile[MAX_PATH];
	UINT      uNumFiles;
	HDROP     hdrop;
	FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	STGMEDIUM stg = { TYMED_HGLOBAL };

	if ( FAILED( pDO->GetData ( &etc, &stg ) ))
		return E_INVALIDARG;

	hdrop = (HDROP) GlobalLock ( stg.hGlobal );

	if ( NULL == hdrop )
	{
		ReleaseStgMedium ( &stg );
		return E_INVALIDARG;
	}

	uNumFiles = DragQueryFile ( hdrop, 0xFFFFFFFF, NULL, 0 );

	for ( UINT uFile = 0; uFile < uNumFiles; uFile++ )
	{
		// Get the next filename.
		if ( 0 == DragQueryFile ( hdrop, uFile, szFile, MAX_PATH ) )
			continue;

		m_lsFiles.push_back ( szFile );
	}

	// Release resources.
	GlobalUnlock ( stg.hGlobal );
	ReleaseStgMedium ( &stg );

	return (m_lsFiles.size() > 0) ? S_OK : E_INVALIDARG;
}

HRESULT CSharpF2::QueryContextMenu ( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
	// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
	if ( uFlags & CMF_DEFAULTONLY )
		return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

	// Add our register/unregister items.
	InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, _T("Rename with SharpF2") );

	// The return value tells the shell how many top-level items we added.
	return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 1 );
}

HRESULT CSharpF2::GetCommandString ( UINT idCmd, UINT uFlags, UINT* puReserved, LPSTR szName, UINT cchMax )
{
	USES_CONVERSION;

	// Check idCmd, it must be 0 since we have only one menu item.
	if ( 0 != idCmd )
		return E_INVALIDARG;

	// If Explorer is asking for a help string, copy our string into the
	// supplied buffer.
	if ( uFlags & GCS_HELPTEXT )
	{
		LPCTSTR szText = _T("Rename selected files with SharpF2");

		if ( uFlags & GCS_UNICODE )
		{
			// We need to cast pszName to a Unicode string, and then use the
			// Unicode string copy API.
			lstrcpynW ( (LPWSTR) szName, T2CW(szText), cchMax );
		}
		else
		{
			// Use the ANSI string copy API to return the help string.
			lstrcpynA ( szName, T2CA(szText), cchMax );
		}

		return S_OK;
	}

	return E_INVALIDARG;
}

HRESULT CSharpF2::InvokeCommand ( LPCMINVOKECOMMANDINFO pInfo )
{
	// If lpVerb really points to a string, ignore this function call and bail out.  
	if ( 0 != HIWORD( pInfo->lpVerb ) )
		return E_INVALIDARG;

	switch ( LOWORD( pInfo->lpVerb ) )
	{
	case 0:
		{
			CRegKey key;
			if(ERROR_SUCCESS != key.Open(HKEY_LOCAL_MACHINE, "Software\\SharpF2", KEY_READ))
				return E_FAIL;

			TCHAR szBuffer[300];
			ULONG cchBuffer = 300;
			key.QueryStringValue("ApplicationPath", szBuffer, &cchBuffer);

			string_list::iterator i = m_lsFiles.begin();
			std::stringstream ss;
			ss << "\"" << szBuffer << "\"";
			for(; i != m_lsFiles.end(); ++i)
			{
				ss << " \"" << (*i).c_str() << "\"";
			}

			STARTUPINFO startup_info = {0};
			startup_info.cb = sizeof startup_info;
			PROCESS_INFORMATION pi = {0};

			DWORD result = CreateProcess(
				szBuffer,
				const_cast<char*>(ss.str().c_str()),
				NULL,
				NULL,
				FALSE, 
				0, 
				NULL,
				NULL, 
				&startup_info, 
				&pi);

			return S_OK;
		}
	default:
		return E_INVALIDARG;
		break;
	}
}
